package com.eastfair.util;

import cn.hutool.core.util.ReflectUtil;
import com.eastfair.annotation.base.SubjectTypeEnum;
import com.eastfair.cache.redis.RedisOps;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.enums.RedisKeyEnum;

/**
 * pv/uv处理工具
 * @ClassName PuvUtils
 * @Description TODO
 * @Author liuxiaobai
 * @Date 2021/8/27 11:35 上午
 * @Version 1.0
 */
public class PuvUtils {


    /**
     * pv属性名
     */
    private static final String FIELD_NAME_PV = "pv";
    /**
     * uv属性名
     */
    private static final String FIELD_NAME_UV = "uv";
    /**
     * pv zSet自增步长
     */
    private static final double INCR_SCORE = 1;
    /**
     * 获取项目级pv
     * @param redisOps redis
     * @param subjectType 内容枚举
     * @param subjectId 内容ID
     * @return pv
     */
    public static long getPvProject(RedisOps redisOps, SubjectTypeEnum subjectType,Long subjectId) {
        String key = String.format(RedisKeyEnum.PV_PROJECT.getKey(),ContextUtil.getProjectId(),subjectType.getCode());
        Double pv = redisOps.zScore(key,subjectId);
        return pv == null ? 0 : pv.longValue();
    }
    /**
     * 获取展会级pv
     * @param redisOps redis
     * @param subjectType 内容枚举
     * @param subjectId 内容ID
     * @return pv
     */
    public static long getPvExhibition(RedisOps redisOps,SubjectTypeEnum subjectType,Long subjectId) {
        String key = String.format(RedisKeyEnum.PV_EXHIBITION.getKey(),ContextUtil.getExhibitionId(),subjectType.getCode());
        Double pv = redisOps.zScore(key,subjectId);
        return pv == null ? 0 : pv.longValue();
    }
    /**
     * pv记录
     * @param redisOps redis
     * @param subjectType 内容类型
     * @param subjectId 内容ID
     * @param ratio 自定义增量
     */
    public static void addPv(RedisOps redisOps ,SubjectTypeEnum subjectType,Long subjectId,Integer ratio) {
        String projectKey = String.format(RedisKeyEnum.PV_PROJECT.getKey(),ContextUtil.getProjectId(),subjectType.getCode());
        String exhibitionKey = String.format(RedisKeyEnum.PV_EXHIBITION.getKey(),ContextUtil.getExhibitionId(),subjectType.getCode());
        if (ratio == null) {
            ratio = 0;
        }
        redisOps.zIncrBy(projectKey,subjectId,INCR_SCORE + ratio);
        redisOps.zIncrBy(exhibitionKey,subjectId,INCR_SCORE + ratio);
    }


    /**
     * 获取项目级uv
     * @param redisOps redis
     * @param subjectType 内容类型
     * @param subjectId 内容ID
     * @return uv数值
     */
    public static long getUvProject(RedisOps redisOps, SubjectTypeEnum subjectType,Long subjectId) {
        String key = String.format(RedisKeyEnum.UV_PROJECT.getKey(),ContextUtil.getProjectId(),subjectType,subjectId);
        return redisOps.pfCount(key);
    }
    /**
     * 获取展会级uv
     * @param redisOps redis
     * @param subjectType 内容类型
     * @param subjectId 内容ID
     * @return uv数值
     */
    public static long getUvExhibition(RedisOps redisOps, SubjectTypeEnum subjectType,Long subjectId) {
        String key = String.format(RedisKeyEnum.UV_EXHIBITION.getKey(),ContextUtil.getExhibitionId(),subjectType,subjectId);
        return redisOps.pfCount(key);
    }
    /**
     * 记录uv
     * @param redisOps redis
     * @param subjectType 内容type
     * @param subjectId 内容ID
     */
    public static void addUv (RedisOps redisOps, SubjectTypeEnum subjectType,Long subjectId) {
        String projectKey = String.format(RedisKeyEnum.UV_PROJECT.getKey(), ContextUtil.getProjectId(),subjectType,subjectId);
        String exhibitionKey = String.format(RedisKeyEnum.UV_EXHIBITION.getKey(), ContextUtil.getExhibitionId(),subjectType,subjectId);
        redisOps.pfAdd(projectKey,ContextUtil.getUserId());
        redisOps.pfAdd(exhibitionKey,ContextUtil.getUserId());
    }

    /**
     * 记录展会级和项目级pv、uv 并set进传入的obj
     * @param redisOps redis
     * @param obj 接收pv、uv的obj
     * @param subjectType 实体类型
     * @param subjectId 记录/获取的实体ID
     * @param ratio 自定义增量
     */
    public static<T> void handlePuv(RedisOps redisOps,T obj,SubjectTypeEnum subjectType,Long subjectId,Integer ratio) {
        PuvUtils.addUv(redisOps,subjectType,subjectId);
        PuvUtils.addPv(redisOps,subjectType,subjectId,ratio);
        //获取展会级pv、uv
        Long pv = PuvUtils.getPvExhibition(redisOps,subjectType,subjectId);
        Long uv = PuvUtils.getUvExhibition(redisOps,subjectType,subjectId);
        ReflectUtil.setFieldValue(obj,FIELD_NAME_PV,pv);
        ReflectUtil.setFieldValue(obj,FIELD_NAME_UV,uv);
    }

}
